home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / bblink.c < prev    next >
C/C++ Source or Header  |  1994-01-15  |  6KB  |  276 lines

  1. /*
  2.  * block profile support for gcc.
  3.  *    ++jrb    bammi@cadence.com
  4.  */
  5. #include <compiler.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <time.h>
  9. #include <string.h>
  10.  
  11. /* block count struct produced by gcc -a */
  12. struct bb {
  13.     long    initialized;    /* has __bb_init_func been called */
  14.     const char    *filename;    /* filename for .d file          */
  15.     long    *counts;    /* address of block count table   */
  16.     long    ncounts;    /* sizeof block count table       */
  17.                     /* ie: # of basic blocks in file  */
  18.     struct bb *next;        /* in memory link to next struct  */
  19.     const unsigned long    *addresses; /* addr of basic block address table */
  20.                 /* size of address table == ncounts+1 */
  21.  
  22.     /* Older GCC's did not emit these fields.  */
  23.     long nwords;
  24.     const char **functions;
  25.     const long *line_nums;
  26.     const char **filenames;
  27. };
  28.  
  29. void __bb_init_func __PROTO((struct bb *));
  30. static void exit_func __PROTO((void));      /* installed to be called at exit */
  31. #ifdef OLD
  32. static void save_info __PROTO((struct bb *));
  33. #endif
  34.  
  35. /* vars */
  36. static struct bb *bb_head = NULL; /* list of all bb_count for which 
  37.                        __bb_init_func has been called */
  38. static char first_call = 1;    /* flags first call to __bb_init_func */
  39. static char at_exit_failed = 0; /* flag to indicate that atexit() failed */
  40.  
  41. /*
  42.  * called by gcc -a generated code on first entry into a function
  43.  */
  44. void __bb_init_func(bb_count)
  45. struct bb *bb_count;
  46. {
  47.     if(at_exit_failed)
  48.     return;
  49.  
  50.     if(first_call)
  51.     {
  52.     if(atexit(exit_func))
  53.     {
  54.         fprintf(stderr, "Failed to install exit function. No block \
  55. profile information will be saved\n");
  56.         at_exit_failed = 1;
  57.         return;
  58.         }
  59.     first_call = 0;
  60.     }
  61.  
  62.     if(bb_count->initialized == 0)
  63.     {   /* link into list of bb_counts */
  64.     bb_count->next = bb_head;
  65.     bb_head = bb_count;
  66.     bb_count->initialized = 1;
  67.     }
  68. }
  69.  
  70. #ifdef OLD
  71. /*
  72.  * called on normal exit
  73.  *   write out block profile files for each bb_count struct in list.
  74.  */
  75. static void exit_func()
  76. {
  77.     struct bb *p;
  78.  
  79.     for(p = bb_head; p; p = p->next)
  80.        save_info(p);
  81. }
  82.  
  83. typedef struct {
  84.     long    lineno;        /* start of block */
  85.     long    count;          /* # executions (cumulative over runs)  */
  86. } DINFO;
  87.  
  88. /*
  89.  * given a bb_count struct, save info into .d file
  90.  */
  91. static void save_info(p)
  92. struct bb *p;
  93. {
  94.     FILE *fp;
  95.     long i, *bcounts;
  96.     DINFO *dinfo = malloc(p->ncounts * sizeof(DINFO));
  97.  
  98.     if(!dinfo)
  99.     {
  100.     fprintf(stderr, "No memory to process %s. Skipped\n", p->filename);
  101.         return;
  102.     }
  103.  
  104.     if((fp = fopen(p->filename, "r")) == NULL)
  105.     {
  106.     fprintf(stderr,"Failed to open %s for read. Skipped\n", p->filename);
  107.     free(dinfo);
  108.     return;
  109.     }
  110.     /* read .d file & accumulate counts */
  111.     for(i = 0, bcounts = p->counts;
  112.         fscanf(fp, "%ld%ld", &dinfo[i].lineno, &dinfo[i].count) == 2; i++)
  113.     {
  114.     if(i >= p->ncounts)
  115.         {
  116.           fprintf(stderr, "Block counts in %s exceed expected %ld, rest skipped\n",
  117.             p->filename, p->ncounts);
  118.           break;
  119.         }
  120.     dinfo[i].count += bcounts[i];
  121.     }
  122.     fclose(fp);
  123.     if(i < p->ncounts)
  124.     {
  125.       fprintf(stderr, "Warning Block counts in %s less than expected %ld\n",
  126.             p->filename, p->ncounts);
  127.     }
  128.     if((fp = fopen(p->filename, "w")) == NULL)
  129.     {
  130.     fprintf(stderr,"Failed to open %s for write. Skipped\n", p->filename);
  131.     free(dinfo);
  132.     return;
  133.     }
  134.     for(i = 0; i < p->ncounts; i++)
  135.     {
  136.     if(fprintf(fp, "\t%ld\t%ld\n", dinfo[i].lineno, dinfo[i].count) == EOF)
  137.     {
  138.        fprintf(stderr,"Write Failed to %s\n", p->filename);
  139.        free(dinfo);
  140.        fclose(fp);
  141.        return;
  142.         }
  143.     }
  144.     fclose(fp);
  145.     free(dinfo);
  146. }
  147.  
  148. #else /* !OLD */
  149.  
  150. /* from GCC's libgcc2.c */
  151.  
  152. /* Return the number of digits needed to print a value */
  153. /* __inline__ */ static int num_digits (long value, int base)
  154. {
  155.   int minus = (value < 0 && base != 16);
  156.   unsigned long v = (minus) ? -value : value;
  157.   int ret = minus;
  158.  
  159.   do
  160.     {
  161.       v /= base;
  162.       ret++;
  163.     }
  164.   while (v);
  165.  
  166.   return ret;
  167. }
  168.  
  169. static void
  170. exit_func (void)
  171. {
  172.   FILE *file = fopen ("bb.out", "a");
  173.   time_t time_value;
  174.  
  175.   if (!file)
  176.     perror ("bb.out");
  177.  
  178.   else
  179.     {
  180.       struct bb *ptr;
  181.  
  182.       time (&time_value);
  183.       fprintf (file, "Basic block profiling finished on %s\n", ctime (&time_value));
  184.  
  185.       /* We check the length field explicitly in order to allow compatibility
  186.      with older GCC's which did not provide it.  */
  187.  
  188.       for (ptr = bb_head; ptr != (struct bb *) NULL; ptr = ptr->next)
  189.     {
  190.       int i;
  191.       int func_p    = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
  192.       int line_p    = (func_p && ptr->line_nums);
  193.       int file_p    = (func_p && ptr->filenames);
  194.       long ncounts    = ptr->ncounts;
  195.       long cnt_max  = 0;
  196.       long line_max = 0;
  197.       long addr_max = 0;
  198.       int file_len    = 0;
  199.       int func_len    = 0;
  200.       int blk_len    = num_digits (ncounts, 10);
  201.       int cnt_len;
  202.       int line_len;
  203.       int addr_len;
  204.  
  205.       fprintf (file, "File %s, %ld basic blocks \n\n",
  206.            ptr->filename, ncounts);
  207.  
  208.       /* Get max values for each field.  */
  209.       for (i = 0; i < ncounts; i++)
  210.         {
  211.           const char *p;
  212.           int len;
  213.  
  214.           if (cnt_max < ptr->counts[i])
  215.         cnt_max = ptr->counts[i];
  216.  
  217.           if (addr_max < ptr->addresses[i])
  218.         addr_max = ptr->addresses[i];
  219.  
  220.           if (line_p && line_max < ptr->line_nums[i])
  221.         line_max = ptr->line_nums[i];
  222.  
  223.           if (func_p)
  224.         {
  225.           p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
  226.           len = strlen (p);
  227.           if (func_len < len)
  228.             func_len = len;
  229.         }
  230.  
  231.           if (file_p)
  232.         {
  233.           p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
  234.           len = strlen (p);
  235.           if (file_len < len)
  236.             file_len = len;
  237.         }
  238.         }
  239.  
  240.       addr_len = num_digits (addr_max, 16);
  241.       cnt_len  = num_digits (cnt_max, 10);
  242.       line_len = num_digits (line_max, 10);
  243.  
  244.       /* Now print out the basic block information.  */
  245.       for (i = 0; i < ncounts; i++)
  246.         {
  247.           fprintf (file,
  248.                "    Block #%*d: executed %*ld time(s) address= 0x%.*lx",
  249.                blk_len, i+1,
  250.                cnt_len, ptr->counts[i],
  251.                addr_len, ptr->addresses[i]);
  252.  
  253.           if (func_p)
  254.         fprintf (file, " function= %-*s", func_len,
  255.              (ptr->functions[i]) ? ptr->functions[i] : "<none>");
  256.  
  257.           if (line_p)
  258.         fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
  259.  
  260.           if (file_p)
  261.         fprintf (file, " file= %s",
  262.              (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
  263.  
  264.           fprintf (file, "\n");
  265.         }
  266.  
  267.       fprintf (file, "\n");
  268.       fflush (file);
  269.     }
  270.  
  271.       fprintf (file, "\n\n");
  272.       fclose (file);
  273.     }
  274. }
  275. #endif /* OLD */
  276.